package com.ouyunc.oauth2.config.override;


import com.alibaba.fastjson.JSON;
import com.ouyunc.common.constant.Auth2Constant;
import com.ouyunc.oauth2.service.IUserDetailsService;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;

import java.util.Map;

/**
 * @Author fangzhenxun
 * @Description 主要在刷新token的时候用来验证用户信息
 * 这里复制UserDetailsByNameServiceWrapper中的代码，然后重写loadUserDetails(T authentication)
 * @Date 2020/4/22 14:03
 **/
public class IUserDetailsByNameServiceWrapper <T extends Authentication> implements AuthenticationUserDetailsService<T>, InitializingBean {

    /**
     * 替换自己的service
     **/
    private IUserDetailsService iuserDetailsService = null;

    /**
     * Constructs an empty wrapper for compatibility with Spring Security 2.0.x's method
     * of using a setter.
     */
    public IUserDetailsByNameServiceWrapper() {
        // constructor for backwards compatibility with 2.0
    }

    /**
     * Constructs a new wrapper using the supplied
     * {@link org.springframework.security.core.userdetails.UserDetailsService} as the
     * service to delegate to.
     *
     * @param userDetailsService the UserDetailsService to delegate to.
     */
    public IUserDetailsByNameServiceWrapper(final IUserDetailsService userDetailsService) {
        Assert.notNull(userDetailsService, "userDetailsService cannot be null.");
        this.iuserDetailsService = userDetailsService;
    }

    /**
     * Check whether all required properties have been set.
     *
     * @see InitializingBean#afterPropertiesSet()
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(this.iuserDetailsService, "UserDetailsService must be set");
    }


    /**
     * @Author fangzhenxun
     * @Description  从包装的IUserDetailsService实现中获取UserDetails对象,、
     * 在这里进行替换自己的 IUserDetailsService的实现，并且添加添加扩展map,为了再次认证
     * @Date 2020/4/22 14:07
     * @param authentication
     * @return org.springframework.security.core.userdetails.UserDetails
     **/
    @Override
    public UserDetails loadUserDetails(T authentication) throws UsernameNotFoundException {
        // 自定义添加
        Map<String,Object> authenticationDetailsMap = (Map<String, Object>) authentication.getDetails();
        //自定义添加,扩展字段
        Map<String, Object> extendMap = JSON.parseObject((String) authenticationDetailsMap.get(Auth2Constant.EXTEND_MAP), Map.class);
        //认证收授权的刷新token
        if (MapUtils.isEmpty(extendMap)) {
            return this.iuserDetailsService.loadUserByUsername(authentication.getName());
        }
        //用户名密码的刷新token，使用自定义的loadUserByUserName
        return this.iuserDetailsService.loadUserByUsername(authentication.getName(), extendMap);
    }

    /**
     * Set the wrapped UserDetailsService implementation
     *
     * @param aUserDetailsService The wrapped UserDetailsService to set
     */
    public void setUserDetailsService(IUserDetailsService aUserDetailsService) {
        this.iuserDetailsService = aUserDetailsService;
    }

}
